﻿/********************************************************************************
* Copyright 2010 Zane Thorn (zane.thorn@gmail.com)                              *
*                                                                               *
* NeturalMath is free software: you can redistribute it and/or modify           *
* it under the terms of the GNU Lesser General Public License as published by   *
* the Free Software Foundation, either version 3 of the License, or             *
* (at your option) any later version.                                           *
*                                                                               *
* NeturalMath is distributed in the hope that it will be useful,                *
* but WITHOUT ANY WARRANTY; without even the implied warranty of                *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
* GNU Lesser General Public License for more details.                           *
*                                                                               *
* You should have received a copy of the GNU Lesser General Public License      *
* along with NeturalMath.  If not, see <http://www.gnu.org/licenses/>.          *
********************************************************************************/

using System;

namespace NeturalMath
{
    /// <summary>
    /// Represents a void value, or a value with no type information
    /// </summary>
    /// <remarks>
    /// ! NeturalMath Language Definition and Syntax
    /// !! this Data Type
    /// The this data type represents a value that cannot be determined or has no meaning.  In a sense, a void is an undefined or unquantifiable value.  The void data type cannot be directly created, and is only represented through the void constant.  The void data type behaves as something of a hybrid between the concept of {{void}} and {{null}} in C#.  It is more closely relate to the {{void}} type in C.
    /// 
    /// !!! Type information
    /// The this data type will return the [String] <c>'void'</c> when queried.
    /// <code>
    /// :> x = void
    /// :> numType = type(x)
    /// :> print numType
    /// 
    /// 'void'
    /// </code>
    /// 
    /// If output, the void data type will return the literal <c>void</c>
    /// <code>
    /// :> x = void
    /// :> print x
    /// 
    /// void
    /// </code>
    /// 
    /// 
    /// !!! Operations
    /// The void Data Type does not participate in any operations.  Any operation containing a void value will always return void as a result.
    /// 
    /// !!! Literals
    /// this variables can only be assigned by using the {void} constant.
    /// <code>
    /// :> a = void
    /// </code>
    /// 
    /// !!! Conversions
    /// Voids exhibit the following behaviors when converted to other types:
    /// !!!! [Bool]
    /// A void converted to a bool will always yield [false].
    /// 
    /// !!!! [Complex]
    /// Voids cannot be converted to complex values.  Any attempt to convert a void to a complex will yield an error.
    /// 
    /// !!!! [Number]
    /// Voids converted to a number will always return the [undefined] constant.
    /// 
    /// !!!! [Range]
    /// Voids cannot be converted to a range.  Any attempt to convert a void to a range will yield an error
    /// 
    /// !!!! [Set]
    /// Voids converted to a set will always yield the [empty set].
    /// 
    /// !!!! [String]
    /// Voids converted to a string will yield an [empty string].
    /// 
    /// !!!! [Units]
    /// Voids cannot be converted to a unit.  Any attempt to convert a void to a unit will yield an error.
    /// 
    /// !!! Functions
    /// The following [System Functions] consume the this data type:
    /// isvoid]
    /// [type]
    /// </remarks>
    public sealed class VoidValue:MathValue
    {
        #region Constructors

        /// <summary>
        /// Creates a new instance of the void data type.
        /// </summary>
        /// <remarks>
        /// This should only ever be called when constructing the void constant in the MathValue class.
        /// </remarks>
        internal VoidValue(MathRuntime runtime) 
            : base(ValueTypes.Void, "void", null,runtime)
        {
        }

        #endregion

        #region Helper Methods

        #region Basic Math Functions

        /// <summary>
        /// Overrides basic Add functionality.
        /// </summary>
        /// <remarks>
        /// All operations using this will always return this
        /// </remarks>
        /// <param name="arg">The value to be added</param>
        /// <returns>Always returns void</returns>
        protected override MathValue Add(MathValue arg)
        {
            return this;
        }

        /// <summary>
        /// Overrides basic Subtract functionality.
        /// </summary>
        /// <remarks>
        /// All operations using this will always return this
        /// </remarks>
        /// <param name="arg">The value to be subtracted</param>
        /// <returns>Always returns void</returns>
        protected override MathValue Subtract(MathValue arg)
        {
            return this;
        }

        /// <summary>
        /// Overrides basic Multiply functionality.
        /// </summary>
        /// <remarks>
        /// All operations using this will always return this
        /// </remarks>
        /// <param name="arg">The value to be multiplied</param>
        /// <returns>Always returns void</returns>
        protected override MathValue Multiply(MathValue arg)
        {
            return this;
        }

        /// <summary>
        /// Overrides basic Divide functionality.
        /// </summary>
        /// <remarks>
        /// All operations using this will always return this
        /// </remarks>
        /// <param name="arg">The value to be divided</param>
        /// <returns>Always returns void</returns>
        protected override MathValue Divide(MathValue arg)
        {
            return this;
        }

        /// <summary>
        /// Overrides basic Modulo functionality.
        /// </summary>
        /// <remarks>
        /// All operations using this will always return this
        /// </remarks>
        /// <param name="arg">The value to be divided</param>
        /// <returns>Always returns void</returns>
        protected override MathValue Modulo(MathValue arg)
        {
            return this;
        }

        /// <summary>
        /// Overrides basic Power functionality.
        /// </summary>
        /// <remarks>
        /// All operations using this will always return this
        /// </remarks>
        /// <param name="arg">The value of the exponent</param>
        /// <returns>Always returns void</returns>
        protected override MathValue Power(MathValue arg)
        {
            return this;
        }

        #endregion

        #region Logical Functions

        /// <summary>
        /// Performs an AND operation on the value
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override MathValue And(MathValue arg)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Performs an OR operation on the value
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override MathValue Or(MathValue arg)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Performsn an XOR operaton on the values
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override MathValue Xor(MathValue arg)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Relational Functions

        /// <summary>
        /// Determines if this value is less than the argument provided
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override bool? IsLessThan(MathValue arg)
        {
            if (arg == this)
                return false;
            return null;
        }

        /// <summary>
        /// Determines if the value is greater than  to the value provided
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override bool? IsGreaterThan(MathValue arg)
        {
            if (arg == this)
                return false;
            return null;
        }

        #endregion

        #region Conversion Functions


        /// <summary>
        /// Returns void
        /// </summary>
        /// <returns></returns>
        protected override MathValue Flip()
        {
            return this;
        }

        /// <summary>
        /// Attempts to convert the value to true
        /// </summary>
        /// <returns>Always returns false</returns>
        protected override bool IsTrue()
        {
            return false;
        }


        /// <summary>
        /// Attempts to convert the value to a negative
        /// </summary>
        /// <returns>Always return </returns>
        protected override MathValue ToMinus()
        {
            return this;
        }

        /// <summary>
        /// Converts the underlying data to a string
        /// </summary>
        /// <returns>Always returns an empty string</returns>
        protected internal override MathValue ConvertToString()
        {
            return Runtime.EmptyString;
        }

        /// <summary>
        /// Converts the underlying data to a number
        /// </summary>
        /// <returns>Always returns the undefined constant</returns>
        protected internal override MathValue ConvertToNumber()
        {
            return Runtime.Undefined;
        }

        /// <summary>
        /// Converts the underlying data to a boolean
        /// </summary>
        /// <returns>Always returns false</returns>
        protected internal override MathValue ConvertToBoolean()
        {
            return Runtime.False;
        }

        /// <summary>
        /// Converts the provided value to void
        /// </summary>
        /// <param name="value">The value to convert</param>
        /// <returns>this</returns>
        protected override MathValue ConvertToNativeValue(MathValue value)
        {
            return value;
        }

        /// <summary>
        /// Converts the value to a range
        /// </summary>
        /// <returns></returns>
        protected internal override MathValue ConvertToRange()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Converts the value to a complex
        /// </summary>
        /// <returns></returns>
        protected internal override MathValue ConvertToComplex()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Converts the value to a unit, based on the specified unit measure
        /// </summary>
        /// <param name="measure"></param>
        /// <returns></returns>
        protected internal override MathValue ConvertToUnit(Units.UnitMeasure measure)
        {
            throw new NotImplementedException();
        }

        #endregion

        /// <summary>
        /// Gets a string representation of the data
        /// </summary>
        /// <returns></returns>
        protected override string GetToString()
        {
            return "void";
        }

        #endregion
    }
}
